/*
 * Copyright 2017 Baiyyy
 * @(#)UploadService.java
 */

package com.byyy.ccts.extend.zx.service.impl;

import com.byyy.ccts.core.common.service.impl.CommonServiceImpl;
import com.byyy.ccts.core.message.rocketmq.OAProducer;
import com.byyy.ccts.core.utils.DateUtils;
import com.byyy.ccts.core.utils.SpringContextHolder;
import com.byyy.ccts.extend.zx.entity.Record;
import com.byyy.ccts.extend.zx.mapper.RecordMapper;
import com.byyy.ccts.extend.zx.service.IRecordService;
import com.byyy.ccts.modules.cc.Global;
import com.byyy.ccts.modules.cc.entity.ccts.*;
import com.byyy.ccts.modules.cc.mapper.DeviceMapper;
import com.byyy.ccts.modules.cc.mapper.DeviceWarningLogMapper;
import com.byyy.ccts.modules.cc.mapper.HumitureMapper;
import com.byyy.ccts.modules.cc.service.IChillCarService;
import com.byyy.ccts.modules.cc.service.IHumitureService;
import com.byyy.ccts.modules.cc.service.IPsZcdMxService;
import com.byyy.ccts.modules.sys.entity.Log;
import com.byyy.ccts.modules.sys.service.IParamService;
import com.byyy.ccts.modules.sys.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;

/**
 * 志祥领域温度记录实现类
 * Created by DELL on 2018-11-19.
 */
@Transactional
@Service("recordService")
public class RecordService extends CommonServiceImpl<RecordMapper, Record> implements IRecordService {

    @Autowired
    private IChillCarService chillCarService;

    @Autowired
    private IHumitureService humitureService;

    @Autowired
    private IPsZcdMxService psZcdMxService;

    @Autowired
    private DeviceWarningLogMapper deviceWarningLogMapper;

    @Autowired
    private HumitureMapper humitureMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    /** 参数服务类 */
    @Autowired
    private IParamService paramService;

    @Override
    public void syncCarTempTask() {
        // 获取冷链平台最新的车辆数据
        Timestamp dt = null;
        List<TSHumiture> humitureList = null;
        List<TAChillCar> chillCarList = this.chillCarService.selectList(null);
        List<Record> recordList = null;
        List<TADevice> deviceList = null;
        List<String> deviceIdList = null;
        if (chillCarList == null || chillCarList.size() < 1) {
            return;
        }

        for (TAChillCar car : chillCarList) {
            deviceIdList = new ArrayList<>();
            deviceList = this.deviceMapper.queryByCarNo(car.getId());
            for (TADevice device : deviceList) {
                deviceIdList.add(device.getSn());
            }

            humitureList = this.humitureMapper.queryLastedHumitureInfoNoLimit(deviceIdList);
            if (humitureList == null || humitureList.size() < 1) {
                dt = new Timestamp(DateUtils.addHours(new Date(), -1).getTime());
            }
            else {
                dt = humitureList.get(0).getCollectTime();
            }

            recordList = this.baseMapper.queryByNameAndTime(car.getPlateNum(), dt);

            if (recordList == null || recordList.size() < 1) {
                continue;
            }

            humitureList = this.conv2Humiture(recordList, deviceList);
            this.tempWarning(car, humitureList);
            this.humitureService.insertBatch(humitureList);
        }

    }

    /**
     * 将Record转为Humiture
     * @param recordList
     * @return
     */
    private List<TSHumiture> conv2Humiture(List<Record> recordList, List<TADevice> deviceList) {
        List<TSHumiture> humitureList = new ArrayList<>();
        TSHumiture humiture = null;
        String sn = null;
        for (Record record : recordList) {
            humiture = new TSHumiture();
            // 根据设备NO查找对应的SN
            for (TADevice device : deviceList) {
                if (record.getIpAddr().equals(device.getNo())) {
                    sn = device.getSn();
                    break;
                }
            }
            humiture.setDeviceSn(sn);
            humiture.setCollectTime(record.getDt());
            humiture.setTemperature(record.getWdz());
            humiture.setHumidity(record.getSdz());
            humitureList.add(humiture);
        }

        return humitureList;
    }


    /**
     * 判断是否存在预警、超温数据
     * 1.根据设备ID寻找在途装车单信息，按开始时间，结束时间(nulls first)排序，获取第一条数据
     * 2.获取预警范围
     * 3.判断是否存在预警信息以及报警信息
     * 4.预警报警信息插入数据库(异步)
     * 5.存在报警信息，则根据设备目前间隔时间(报警后设置为2分钟，恢复后设置为4分钟)
     * 6.发送邮件提醒(RocketMQ)
     * @param tsHumitures
     */
    private void tempWarning(TAChillCar car, List<TSHumiture> tsHumitures) {
        logger.debug("开始冷藏车[{}]在途单据预警、报警处理", car.getPlateNum());
        PsZcdMx psZcdMx = null;
        float wendMin = 0f;
        float wendMax = 0f;
        // 温度预警相关值
        float top_warning = 0f;
        float lower_warning = 0f;
        float limit_warning = 0f;
        TADevice device = null;
        StringBuilder warningSb = new StringBuilder();
        StringBuilder alarmSb = new StringBuilder();
        List<TSHumiture> warningList = new ArrayList<>();
        List<TSHumiture> alarmList = new ArrayList<>();
        // 判断上传温度时间是否在途配送单范围内
        Date beginDate = null;

        // 根据设备ID获取在途装车单，没有的话就返回
        psZcdMx = this.psZcdMxService.selectMxOnTheWayByCar(car.getId());
        if (psZcdMx == null) {
            logger.debug("冷藏车[{}]无在途单据预警、报警，处理完毕", car.getPlateNum());
            return;
        }

        beginDate = psZcdMx.getBeginDate();
        // 判断是否存在报警以及预警信息
        wendMin = psZcdMx.getWendMin();
        wendMax = psZcdMx.getWendMax();
        // 预警下限值
        limit_warning = this.paramService.getFloatValueByCode("WARNING_LOWERLIMIT");
        top_warning = wendMax - Global.FIXED_VALUE - limit_warning;
        // 预警上限值
        limit_warning = this.paramService.getFloatValueByCode("WARNING_UPPERLIMIT");
        lower_warning = wendMin + Global.FIXED_VALUE + limit_warning;


        // 循环判断是否存在超出商品温度预警界限以及报警界限
        alarmSb.append("装车单").append(psZcdMx.getZhuangcdNo()).append("内冷藏车(").append(car.getPlateNum()).append(")");
        warningSb.append("装车单").append(psZcdMx.getZhuangcdNo()).append("内冷藏车(").append(car.getPlateNum()).append(")");
        for (TSHumiture humiture : tsHumitures) {
            // 设备上传温度时间 < 装车单开启时间；说明是无效数据
            if (humiture.getCollectTime().getTime() - beginDate.getTime() < 0) {
                continue;
            }
            // 超过预警信息
            if (humiture.getTemperature() >= top_warning || humiture.getTemperature() <= lower_warning) {
                device = this.deviceMapper.selectBySn(humiture.getDeviceSn());
                // 超过报警信息
                if (humiture.getTemperature() > wendMax || humiture.getTemperature() < wendMin) {
                    alarmList.add(humiture);
                    alarmSb.append("测点").append(device.getNo())
                            .append("于").append(DateUtils.formatDate(humiture.getCollectTime(), Global.PATTERN_YYYYMMMDD_HHMMSS))
                            .append("时温度为").append(humiture.getTemperature()).append(",标准温度为").append(wendMin).append("-")
                            .append(wendMax).append(";");
                }
                // 预警报警之间
                else {
                    warningList.add(humiture);
                    warningSb.append("测点").append(device.getNo())
                            .append("于").append(DateUtils.formatDate(humiture.getCollectTime(), Global.PATTERN_YYYYMMMDD_HHMMSS))
                            .append("时温度为").append(humiture.getTemperature()).append(",标准温度为").append(wendMin).append("-")
                            .append(wendMax).append(";");
                }
            }

        }

        if (warningList != null && warningList.size() > 0) {
            OAProducer oAProducer = (OAProducer) SpringContextHolder.getBean("oAProducer");
            oAProducer.sendOAMail("mailWarning" + psZcdMx.getCangku(), "冷链温度预警", warningSb.toString());
            logger.debug("冷藏车[{}]在途单据预警处理({})", car.getPlateNum(), warningSb.toString());
        }

        if (alarmList != null && alarmList.size() > 0) {
            OAProducer oAProducer = (OAProducer) SpringContextHolder.getBean("oAProducer");
            oAProducer.sendOAMail("mailWarning" + psZcdMx.getCangku(), "冷链温度报警", alarmSb.toString());
            logger.debug("冷藏车[{}]在途单据报警处理({})", car.getPlateNum(), alarmSb.toString());
        }

        // 记录日志
        this.writeWarningLog(alarmList, warningList, psZcdMx, car.getId());

        logger.debug("冷藏车[{}]在途单据预警、报警处理完毕", car.getPlateNum());
    }

    /**
     * 写入日志
     * @param alarmList
     * @param warningList
     */
    private void writeWarningLog(List<TSHumiture> alarmList, List<TSHumiture> warningList,
                                 PsZcdMx psZcdMx, String car) {
        TSDeviceWarningLog log = null;
        // 写入温度报警日志
        if (alarmList != null && alarmList.size() > 0) {
            for (TSHumiture temp : alarmList) {
                log = new TSDeviceWarningLog();
                log.setDeviceId(car);
                log.setType(Log.TEMPERATURE_ALARM);
                log.setTitle(psZcdMx.getZhuangcdNo());
                log.setContent(String.valueOf(temp.getTemperature()));
                log.setCollectTime(temp.getCollectTime());
                log.setCreateBy(UserUtils.getByUserName("admin"));
                log.setCreateDate(new Timestamp(System.currentTimeMillis()));
                this.deviceWarningLogMapper.insert(log);
            }

        }
        // 写入温度预警日志
        if (warningList != null && warningList.size() > 0) {
            for (TSHumiture temp : warningList) {
                log = new TSDeviceWarningLog();
                log.setDeviceId(car);
                log.setType(Log.TEMPERATURE_WARNING);
                log.setTitle(psZcdMx.getZhuangcdNo());
                log.setContent(String.valueOf(temp.getTemperature()));
                log.setCollectTime(temp.getCollectTime());
                log.setCreateBy(UserUtils.getByUserName("admin"));
                log.setCreateDate(new Timestamp(System.currentTimeMillis()));
                this.deviceWarningLogMapper.insert(log);
            }
        }
    }


}
